package com.feinno.urcs.group.siputils;

import com.feinno.sdp.MediaDescriptionImpl;
import com.feinno.sip.header.ContentType;
import com.feinno.urcs.content.Sdp;
import com.feinno.urcs.content.UrcsMultipartMimeContent;
import com.feinno.util.StringUtils;

import javax.sdp.SdpException;
import javax.sdp.SessionDescription;
import javax.sip.message.Message;
import java.net.InetSocketAddress;
import java.net.URI;
import java.text.ParseException;
import java.util.Iterator;

/**
 * MSRP的工具类
 *
 * @author Lv.Mingwei
 *
 */
public class MsrpUtils {
    /**
     * 从SIP消息中获取MSRP的地址
     *
     * @param message
     * @return
     */
    public static String getMsrpPath(Message message) throws SdpException, ParseException {
        SessionDescription sdp = getSdp(message);
        if (sdp != null) {
            return getMsrpPath(sdp);
        } else {
            return null;
        }
    }

    /**
     * 从SDP中获取MSRP地址
     *
     * @param sdp
     * @return
     */
    public static String getMsrpPath(SessionDescription sdp) throws SdpException, ParseException {
        return getAttribute(sdp, "path");
    }

    /**
     * 从SIP消息中获取AcceptType
     *
     * @param message
     * @return
     */
    public static String getMsrpAcceptType(Message message) throws SdpException, ParseException {
        SessionDescription sdp = getSdp(message);
        if (sdp != null) {
            return getMsrpAcceptType(sdp);
        } else {
            return null;
        }
    }

    /**
     * 从SDP中获取AcceptType
     *
     * @param sdp
     * @return
     */
    public static String getMsrpAcceptType(SessionDescription sdp) throws SdpException, ParseException {
        return getAttribute(sdp, "accept-types");
    }

    /**
     * 从SIP消息中获取AcceptWrappedType
     *
     * @param message
     * @return
     */
    public static String getMsrpAcceptWrappedType(Message message) throws SdpException, ParseException {
        SessionDescription sdp = getSdp(message);
        if (sdp != null) {
            return getMsrpAcceptWrappedType(sdp);
        } else {
            return null;
        }
    }

    /**
     * 从SDP中获取AcceptWrappedType
     *
     * @param sdp
     * @return
     */
    public static String getMsrpAcceptWrappedType(SessionDescription sdp) throws SdpException, ParseException {
        return getAttribute(sdp, "accept-wrapped-types");
    }

    public static String getAttribute(SessionDescription sdp, String attrName) throws SdpException, ParseException {
        Iterator<?> itMediaDescriptions = sdp.getMediaDescriptions(true).iterator();
        while (itMediaDescriptions.hasNext()) {
            MediaDescriptionImpl md = (MediaDescriptionImpl) itMediaDescriptions.next();
            if (!StringUtils.isNullOrEmpty(md.getAttribute(attrName))) {
                return md.getAttribute(attrName);
            }
        }
        return null;
    }




    public static byte[] createMsrpSdp(URI uri, InetSocketAddress realAddress, boolean isActive, String acceptTypes) {
        return createMsrpSdp(uri, realAddress, isActive, acceptTypes, "");
    }

    public static byte[] createMsrpSdp(URI uri, InetSocketAddress realAddress, boolean isActive, String acceptTypes, String wrappedTypes) {
        String protocol = getMsrpProtocol(uri);
        int port = realAddress.getPort();
        String host = realAddress.getHostString();
        StringBuffer sb = new StringBuffer();
        sb.append("v=0").append("\r\n");
        sb.append("o=- 55935516 0 IN IP4 ").append(host).append("\r\n");
        sb.append("s=-").append("\r\n");
        sb.append("c=IN IP4 ").append(host).append("\r\n");
        sb.append("t=0 0").append("\r\n");
        sb.append("m=message ").append(port).append(protocol).append("\r\n");
        sb.append("a=setup:").append(isActive ? "active" : "passive").append("\r\n");
        sb.append("a=sendrecv").append("\r\n");
        sb.append("a=accept-types:").append(acceptTypes).append("\r\n");
        if (!StringUtils.isNullOrEmpty(wrappedTypes)) {
            sb.append("a=accept-wrapped-types:").append(wrappedTypes).append("\r\n");
        }
        sb.append("a=path:").append(uri).append("\r\n");
        // setFingerprint(sb, uri);
        return sb.toString().getBytes();
    }

    // ================判断操作==============
    public static boolean isTlsProto(Message message) throws SdpException {
        SessionDescription sdp = getSdp(message);
        return isTlsProto(sdp);
    }

    public static boolean isTlsProto(SessionDescription sdp) throws SdpException {
        Iterator<?> itMediaDescriptions = sdp.getMediaDescriptions(true).iterator();
        while (itMediaDescriptions.hasNext()) {
            MediaDescriptionImpl md = (MediaDescriptionImpl) itMediaDescriptions.next();
            String proto = md.getMediaField().getProto().toUpperCase();
            if (proto.contains("TLS")) {
                return true;
            }
        }
        return false;
    }

    public static boolean isActive(SessionDescription sdp) throws SdpException, ParseException {
        Iterator<?> itMediaDescriptions = sdp.getMediaDescriptions(true).iterator();
        while (itMediaDescriptions.hasNext()) {
            MediaDescriptionImpl md = (MediaDescriptionImpl) itMediaDescriptions.next();
            String setup = md.getAttribute("setup");
            return "active".equalsIgnoreCase(setup) || "actpass".equalsIgnoreCase(setup);
        }
        return false;
    }

    public static InetSocketAddress getAddressBySdp(SessionDescription sdp) throws SdpException {
        Iterator<?> itMediaDescriptions = sdp.getMediaDescriptions(true).iterator();
        while (itMediaDescriptions.hasNext()) {
            String host = null;
            int port = 0;
            MediaDescriptionImpl md = (MediaDescriptionImpl) itMediaDescriptions.next();
            if (!StringUtils.isNullOrEmpty(md.getAttribute("path"))) {
                host = md.getAttribute("path");
            }
            if (md.getMedia().getMediaPort() > 0) {
                port = md.getMedia().getMediaPort();
            }
            host = sdp.getConnection().getAddress();
            return new InetSocketAddress(host, port);
        }
        return null;
    }

    // =====================private method====================
    // private static void setFingerprint(StringBuffer sb, URI msrpPath) {
    // String msrpPrefix = msrpPath.getScheme();
    // if (msrpPrefix.equalsIgnoreCase("msrps")) {
    // sb.append("a=fingerprint:").append(MsrpCertStore.FINGER_PRINT);
    // }
    // }

    private static String getMsrpProtocol(URI msrpPath) {
        String msrpPrefix = msrpPath.getScheme();
        String protocol;
        if (msrpPrefix.equalsIgnoreCase("msrps")) {
            protocol = " TCP/TLS/MSRP *";
        } else {
            protocol = " TCP/MSRP *";
        }
        return protocol;
    }

    public static SessionDescription getSdp(Message message) {
        // 如果是HeliumSipMessage，则优先从HeliumSipMessage中取，因为HeliumSipMessage中存在缓存，能提升效率
        UrcsMultipartMimeContent multipartMimeContent = null;
        // if (message instanceof HeliumSipMessage) {
        // multipartMimeContent = ((HeliumSipMessage)
        // message).getMultipartMimeContent();
        // } else {
        multipartMimeContent = UrcsMultipartMimeContent.newInstance((ContentType) message.getHeader(ContentType.NAME),
                message.getRawContent());
        // }
        Sdp sdpContent = multipartMimeContent.getContent(Sdp.class);
        if (sdpContent == null) {
            return null;
        }
        SessionDescription sdp = sdpContent.getSdp();
        return sdp;
    }
}
